package top.hudk.limiter;

import com.google.common.util.concurrent.RateLimiter;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * 请输入描述信息
 *
 * @author HuDongkang
 * @date 2022/8/17 14:42
 */
@Slf4j
public class Test {

    private static final ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(10,10,5,
            TimeUnit.SECONDS,new ArrayBlockingQueue<Runnable>(50), new ThreadPoolExecutor.CallerRunsPolicy());


    private static long timeMillis = System.currentTimeMillis();

    private static long timeMillis2 = System.currentTimeMillis();

    public static void main(String[] args) {
//        String str = String.format("%.1f", (double)0 / 4);
//        log.info("{}", str);
        RateLimiter rateLimiter = RateLimiter.create(3, 10, TimeUnit.SECONDS);
        Rater rater = new Rater();
        long totalReq = 10000;
        for(long i = 0; i < totalReq; i ++){
            rateLimiter.acquire();
            rater.recordEventTimeStamp();
            print(rater);
//            if(System.currentTimeMillis() - timeMillis2 >= 20000L && System.currentTimeMillis() - timeMillis2 < 30000L){
//                rateLimiter.setRate(60);
//            }else if(System.currentTimeMillis() - timeMillis2 >= 40000L && System.currentTimeMillis() - timeMillis2 < 50000L){
//                rateLimiter.setRate(70);
//            } else if(System.currentTimeMillis() - timeMillis2 >= 60000L && System.currentTimeMillis() - timeMillis2 < 70000L){
//                rateLimiter.setRate(30);
//            }
        }
    }

    private static void print(Rater rater){
        long currentTimeMillis = System.currentTimeMillis();
        if(currentTimeMillis - timeMillis >= 1000){
            log.info("当前速率:{}", rater.getRate());
            timeMillis = currentTimeMillis;
        }
    }





    /**
     * 通过记录某一个事件发生的一系列时间戳，来计算该事件发生的频率
     * 只适用于单线程场景
     */
    private static class Rater{

        /**
         * 时间窗口长短（单位：秒）
         */
        private static final int TIME_WINDOW_LENGTH = 3;

        /**
         * 记录保存某事件发生的一系列时间戳(毫秒时间戳)
         */
        private final List<Long> timeStampList = new ArrayList<>();



        public static Rater getRater(){
            return new Rater();
        }

        /**
         * 记录一个事件发生的时间戳
         */
        public void recordEventTimeStamp(){
            //当前时间戳
            long currentTimeMillis = System.currentTimeMillis();
            //时间窗口中最小时间的时间戳
            long secondAgo = currentTimeMillis - (1000 * TIME_WINDOW_LENGTH);

            //记录当前时间戳
            timeStampList.add(currentTimeMillis);
            //删除时间窗口"以外"的时间戳
            outTimeDelete(secondAgo);
        }

        /**
         * 删除集合中早于指定时间戳的元素
         * @param secondAgo 指定时间戳
         */
        private void outTimeDelete(long secondAgo){
            List<Long> deleteTimeStampListTemp = new ArrayList<>();
            for(Long timeStamp : timeStampList){
                if(timeStamp <= secondAgo){
                    deleteTimeStampListTemp.add(timeStamp);
                }
            }
            timeStampList.removeAll(deleteTimeStampListTemp);
        }

        /**
         * 获取事件发生的频率，即每秒次数
         * @return 频率，每秒次数
         */
        public String getRate(){
            outTimeDelete(System.currentTimeMillis() - (1000 * TIME_WINDOW_LENGTH));
            log.info("timeStampList.size():{} | TIME_WINDOW_LENGTH:{} | timeStampList:{}",timeStampList.size(), TIME_WINDOW_LENGTH, timeStampList);
            return String.format("%.1f", (double)timeStampList.size() / TIME_WINDOW_LENGTH);
        }
    }
}
